#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Grafana用户导出对话框模块 - 用于将Zabbix用户导出到Grafana
"""

import logging
import json
import os
import requests
from typing import Dict, List, Any, Optional
from PyQt5.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QLabel, 
    QLineEdit, QPushButton, QFormLayout, QDialogButtonBox,
    QComboBox, QSpinBox, QTabWidget, QWidget, QTextEdit,
    QCheckBox, QMessageBox, QTableWidget, QTableWidgetItem,
    QHeaderView, QGroupBox, QRadioButton, QProgressBar,
    QFileDialog, QListWidget, QListWidgetItem
)
from PyQt5.QtCore import Qt, pyqtSlot, QThread, pyqtSignal
from PyQt5.QtGui import QFont

try:
    from src.zabbix_api import ZabbixAPI
except ImportError:
    # 尝试不同的导入路径
    from zabbix_api import ZabbixAPI

logger = logging.getLogger(__name__)

class GrafanaExportThread(QThread):
    """Grafana导出线程，用于在后台执行用户导出操作"""
    
    # 定义信号
    progress_signal = pyqtSignal(int)
    status_signal = pyqtSignal(str)
    finished_signal = pyqtSignal(bool, str)
    
    def __init__(self, grafana_config, user_list, zabbix_api):
        """
        初始化Grafana导出线程
        
        Args:
            grafana_config (Dict): Grafana配置信息
            user_list (List): 要导出的用户列表
            zabbix_api (ZabbixAPI): ZabbixAPI实例
        """
        super().__init__()
        self.grafana_config = grafana_config
        self.user_list = user_list
        self.zabbix_api = zabbix_api
        self.is_running = False
    
    def run(self):
        """运行线程"""
        self.is_running = True
        
        try:
            # 获取Grafana配置
            url = self.grafana_config['url'].rstrip('/')
            api_key = self.grafana_config['api_key']
            org_id = self.grafana_config.get('org_id', '1')
            default_password = self.grafana_config.get('default_password', 'grafana123')
            
            # 设置API请求头
            headers = {
                'Authorization': f'Bearer {api_key}',
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            }
            
            self.status_signal.emit("正在连接Grafana API...")
            
            # 测试API连接
            try:
                response = requests.get(f"{url}/api/org", headers=headers)
                response.raise_for_status()
                self.status_signal.emit(f"成功连接Grafana API，组织: {response.json().get('name', '')}")
            except Exception as e:
                self.status_signal.emit(f"连接Grafana API失败: {str(e)}")
                self.finished_signal.emit(False, f"连接Grafana API失败: {str(e)}")
                return
            
            # 获取所有用户
            self.status_signal.emit("正在获取Grafana现有用户...")
            try:
                response = requests.get(f"{url}/api/org/users", headers=headers)
                response.raise_for_status()
                existing_users = response.json()
                existing_logins = [user.get('login', '').lower() for user in existing_users]
                self.status_signal.emit(f"获取到 {len(existing_users)} 个现有Grafana用户")
            except Exception as e:
                self.status_signal.emit(f"获取Grafana用户失败: {str(e)}")
                self.finished_signal.emit(False, f"获取Grafana用户失败: {str(e)}")
                return
            
            # 处理每个用户
            total_users = len(self.user_list)
            success_count = 0
            
            for i, user_id in enumerate(self.user_list):
                if not self.is_running:
                    break
                
                # 更新进度
                progress = int((i + 1) / total_users * 100)
                self.progress_signal.emit(progress)
                
                try:
                    # 获取Zabbix用户详情
                    zabbix_user = self.zabbix_api.get_user_by_id(user_id)
                    username = zabbix_user.get('username', '')
                    name = zabbix_user.get('name', '')
                    surname = zabbix_user.get('surname', '')
                    email = zabbix_user.get('email', '')
                    
                    full_name = f"{name} {surname}".strip()
                    if not full_name:
                        full_name = username
                    
                    self.status_signal.emit(f"处理用户 ({i+1}/{total_users}): {username}")
                    
                    # 检查用户是否已存在
                    if username.lower() in existing_logins:
                        self.status_signal.emit(f"用户 {username} 已存在于Grafana中，跳过")
                        continue
                    
                    # 创建用户
                    user_data = {
                        "name": full_name,
                        "login": username,
                        "email": email if email else f"{username}@example.com",
                        "password": default_password,
                        "OrgId": org_id
                    }
                    
                    response = requests.post(
                        f"{url}/api/admin/users",
                        headers=headers,
                        json=user_data
                    )
                    
                    if response.status_code == 200 or response.status_code == 201:
                        success_count += 1
                        self.status_signal.emit(f"成功创建Grafana用户: {username}")
                        
                        # 添加用户到组织
                        new_user_id = response.json().get('id')
                        if new_user_id:
                            # 设置用户角色
                            role_data = {
                                "role": "Editor" # 默认编辑者角色
                            }
                            role_response = requests.patch(
                                f"{url}/api/org/users/{new_user_id}",
                                headers=headers,
                                json=role_data
                            )
                            
                            if role_response.status_code == 200:
                                self.status_signal.emit(f"成功设置用户 {username} 为编辑者角色")
                            else:
                                self.status_signal.emit(f"设置用户 {username} 角色失败: {role_response.text}")
                    else:
                        self.status_signal.emit(f"创建用户 {username} 失败: {response.text}")
                
                except Exception as e:
                    self.status_signal.emit(f"处理用户 {username} 时出错: {str(e)}")
            
            # 导出完成
            if not self.is_running:
                self.finished_signal.emit(False, "操作已取消")
            else:
                self.status_signal.emit(f"导出完成，成功创建 {success_count} 个Grafana用户")
                self.finished_signal.emit(True, f"成功导出 {success_count} 个用户到Grafana")
            
        except Exception as e:
            error_message = f"导出到Grafana失败: {str(e)}"
            logger.error(error_message)
            self.status_signal.emit(error_message)
            self.finished_signal.emit(False, error_message)
    
    def stop(self):
        """停止线程"""
        self.is_running = False

class GrafanaExportDialog(QDialog):
    """Grafana用户导出对话框"""
    
    def __init__(self, api: ZabbixAPI, parent=None):
        """
        初始化Grafana用户导出对话框
        
        Args:
            api (ZabbixAPI): Zabbix API客户端
            parent: 父窗口
        """
        super().__init__(parent)
        self.api = api
        self.export_thread = None
        self.setup_ui()
        self.load_users()
    
    def setup_ui(self):
        """设置UI界面"""
        self.setWindowTitle("导出用户到Grafana")
        self.resize(700, 600)
        self.setModal(True)
        
        # 创建主布局
        main_layout = QVBoxLayout(self)
        
        # Grafana配置组
        config_group = QGroupBox("Grafana配置")
        config_layout = QFormLayout(config_group)
        
        # Grafana URL
        self.url_edit = QLineEdit()
        self.url_edit.setText("http://localhost:3000")
        config_layout.addRow("Grafana URL:", self.url_edit)
        
        # API Key
        self.api_key_edit = QLineEdit()
        self.api_key_edit.setEchoMode(QLineEdit.Password)
        self.api_key_edit.setPlaceholderText("输入Grafana API Key")
        config_layout.addRow("API Key:", self.api_key_edit)
        
        # 组织ID
        self.org_id_spin = QSpinBox()
        self.org_id_spin.setRange(1, 999)
        self.org_id_spin.setValue(1)
        config_layout.addRow("组织ID:", self.org_id_spin)
        
        # 默认密码
        self.password_edit = QLineEdit()
        self.password_edit.setText("grafana123")
        self.password_edit.setEchoMode(QLineEdit.Password)
        config_layout.addRow("默认密码:", self.password_edit)
        
        main_layout.addWidget(config_group)
        
        # 用户选择组
        user_group = QGroupBox("选择要导出的用户")
        user_layout = QVBoxLayout(user_group)
        
        # 搜索区域
        search_layout = QHBoxLayout()
        
        self.search_edit = QLineEdit()
        self.search_edit.setPlaceholderText("搜索用户")
        self.search_edit.textChanged.connect(self.filter_users)
        search_layout.addWidget(self.search_edit)
        
        self.refresh_btn = QPushButton("刷新")
        self.refresh_btn.clicked.connect(self.load_users)
        search_layout.addWidget(self.refresh_btn)
        
        user_layout.addLayout(search_layout)
        
        # 用户列表
        self.user_list = QTableWidget(0, 5)
        self.user_list.setHorizontalHeaderLabels(["选择", "ID", "用户名", "姓名", "邮箱"])
        self.user_list.setSelectionBehavior(QTableWidget.SelectRows)
        self.user_list.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.user_list.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.user_list.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.user_list.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)
        self.user_list.horizontalHeader().setSectionResizeMode(4, QHeaderView.Stretch)
        user_layout.addWidget(self.user_list)
        
        # 选择按钮
        select_layout = QHBoxLayout()
        
        self.select_all_btn = QPushButton("全选")
        self.select_all_btn.clicked.connect(self.select_all_users)
        select_layout.addWidget(self.select_all_btn)
        
        self.select_none_btn = QPushButton("取消全选")
        self.select_none_btn.clicked.connect(self.select_no_users)
        select_layout.addWidget(self.select_none_btn)
        
        user_layout.addLayout(select_layout)
        
        main_layout.addWidget(user_group)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        main_layout.addWidget(self.progress_bar)
        
        # 状态文本
        self.status_text = QTextEdit()
        self.status_text.setReadOnly(True)
        self.status_text.setMaximumHeight(200)  # 增加高度以显示更多日志
        # 设置等宽字体以便更好地显示日志
        font = QFont("Courier New")
        font.setPointSize(9)
        self.status_text.setFont(font)
        # 设置为白底黑字，提高可读性
        self.status_text.setStyleSheet("background-color: white; color: black;")
        main_layout.addWidget(self.status_text)
        
        # 按钮布局
        button_layout = QHBoxLayout()
        
        # 导出按钮
        self.export_button = QPushButton("导出到Grafana")
        self.export_button.clicked.connect(self.on_export)
        button_layout.addWidget(self.export_button)
        
        # 取消按钮
        self.cancel_button = QPushButton("取消")
        self.cancel_button.clicked.connect(self.reject)
        button_layout.addWidget(self.cancel_button)
        
        main_layout.addLayout(button_layout)
    
    def load_users(self):
        """加载用户列表"""
        try:
            # 清空表格
            self.user_list.setRowCount(0)
            
            # 获取所有用户
            users = self.api.get_users()
            
            # 添加到表格
            for i, user in enumerate(users):
                self.user_list.insertRow(i)
                
                # 选择框
                checkbox = QTableWidgetItem()
                checkbox.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                checkbox.setCheckState(Qt.Unchecked)
                self.user_list.setItem(i, 0, checkbox)
                
                # ID
                id_item = QTableWidgetItem(user.get('userid', ''))
                id_item.setFlags(id_item.flags() & ~Qt.ItemIsEditable)
                self.user_list.setItem(i, 1, id_item)
                
                # 用户名
                username_item = QTableWidgetItem(user.get('username', ''))
                username_item.setFlags(username_item.flags() & ~Qt.ItemIsEditable)
                self.user_list.setItem(i, 2, username_item)
                
                # 姓名
                name = f"{user.get('name', '')} {user.get('surname', '')}".strip()
                name_item = QTableWidgetItem(name)
                name_item.setFlags(name_item.flags() & ~Qt.ItemIsEditable)
                self.user_list.setItem(i, 3, name_item)
                
                # 邮箱
                email_item = QTableWidgetItem(user.get('email', ''))
                email_item.setFlags(email_item.flags() & ~Qt.ItemIsEditable)
                self.user_list.setItem(i, 4, email_item)
            
            self.user_list.sortItems(2)  # 按用户名排序
            
        except Exception as e:
            QMessageBox.warning(self, "错误", f"加载用户失败: {str(e)}")
            logger.error(f"加载用户失败: {str(e)}")
    
    def filter_users(self, text):
        """过滤用户列表"""
        text = text.lower()
        for i in range(self.user_list.rowCount()):
            username = self.user_list.item(i, 2).text().lower()
            name = self.user_list.item(i, 3).text().lower()
            email = self.user_list.item(i, 4).text().lower()
            
            self.user_list.setRowHidden(
                i, text and text not in username and text not in name and text not in email
            )
    
    def select_all_users(self):
        """选择所有用户"""
        for i in range(self.user_list.rowCount()):
            if not self.user_list.isRowHidden(i):
                self.user_list.item(i, 0).setCheckState(Qt.Checked)
    
    def select_no_users(self):
        """取消选择所有用户"""
        for i in range(self.user_list.rowCount()):
            self.user_list.item(i, 0).setCheckState(Qt.Unchecked)
    
    def on_export(self):
        """导出用户到Grafana"""
        # 获取选中的用户
        selected_users = []
        for i in range(self.user_list.rowCount()):
            if self.user_list.item(i, 0).checkState() == Qt.Checked:
                user_id = self.user_list.item(i, 1).text()
                selected_users.append(user_id)
        
        if not selected_users:
            QMessageBox.warning(self, "警告", "请选择至少一个用户进行导出")
            return
        
        # 获取Grafana配置
        grafana_config = {
            'url': self.url_edit.text(),
            'api_key': self.api_key_edit.text(),
            'org_id': str(self.org_id_spin.value()),
            'default_password': self.password_edit.text()
        }
        
        if not grafana_config['url'] or not grafana_config['api_key']:
            QMessageBox.warning(self, "警告", "请输入Grafana URL和API Key")
            return
        
        # 确认导出
        reply = QMessageBox.question(
            self,
            "确认导出",
            f"将导出 {len(selected_users)} 个用户到Grafana，继续吗？",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )
        
        if reply != QMessageBox.Yes:
            return
        
        # 禁用导出按钮
        self.export_button.setEnabled(False)
        self.export_button.setText("导出中...")
        
        # 清空状态
        self.status_text.clear()
        self.progress_bar.setValue(0)
        
        # 创建并启动导出线程
        self.export_thread = GrafanaExportThread(grafana_config, selected_users, self.api)
        self.export_thread.progress_signal.connect(self.update_progress)
        self.export_thread.status_signal.connect(self.update_status)
        self.export_thread.finished_signal.connect(self.export_finished)
        self.export_thread.start()
        
        # 改变取消按钮行为
        self.cancel_button.setText("停止")
        self.cancel_button.clicked.disconnect()
        self.cancel_button.clicked.connect(self.stop_export)
    
    def update_progress(self, value):
        """更新进度条"""
        self.progress_bar.setValue(value)
    
    def update_status(self, message):
        """更新状态文本"""
        # 添加时间戳使日志更清晰
        from datetime import datetime
        timestamp = datetime.now().strftime("%H:%M:%S")
        formatted_message = f"[{timestamp}] {message}"
        
        # 添加日志到状态文本框
        self.status_text.append(formatted_message)
        # 自动滚动到底部
        self.status_text.verticalScrollBar().setValue(
            self.status_text.verticalScrollBar().maximum()
        )
        
        # 同时写入到日志系统
        logger.info(message)
    
    def export_finished(self, success, message):
        """导出完成处理"""
        # 恢复按钮状态
        self.export_button.setEnabled(True)
        self.export_button.setText("导出到Grafana")
        
        self.cancel_button.setText("关闭")
        self.cancel_button.clicked.disconnect()
        self.cancel_button.clicked.connect(self.accept)
        
        # 显示结果
        if success:
            QMessageBox.information(self, "导出完成", message)
        else:
            QMessageBox.warning(self, "导出失败", message)
    
    def stop_export(self):
        """停止导出"""
        if self.export_thread and self.export_thread.isRunning():
            self.export_thread.stop()
            self.update_status("正在停止导出，请稍候...")
    
    def closeEvent(self, event):
        """窗口关闭事件处理"""
        if self.export_thread and self.export_thread.isRunning():
            # 询问用户是否确认退出
            reply = QMessageBox.question(
                self,
                "确认退出",
                "导出任务正在进行中，确定要退出吗？",
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No
            )
            
            if reply == QMessageBox.Yes:
                self.export_thread.stop()
            else:
                event.ignore()
                return
        
        super().closeEvent(event) 